package de.acagamics.roteschlupfmuetze.level;

import java.util.Random;

import java.awt.image.BufferedImage;

import com.golden.gamedev.object.Sprite;
import com.golden.gamedev.object.SpriteGroup;

import de.acagamics.roteschlupfmuetze.RoteSchlupfmuetze;
import de.acagamics.roteschlupfmuetze.data.LevelData;
import de.acagamics.roteschlupfmuetze.core.ImageHelper;

public class GridGenerator {
	BufferedImage fill;
	BufferedImage[] edgeToLeft, edgeToRight;
	BufferedImage[] longEdgeToLeft, longEdgeToRight;
	BufferedImage[] cornerToLeft, cornerToRight;
	BufferedImage[] surface;
	BufferedImage[] pitSurface;
	
	private Random random = new Random();
	
	int LONG_EDGE_HEIGHT = 10;
	int SHORT_EDGE_HEIGHT = 5;
	
	private SpriteGroup STATIC, MOVABLE, COLLISION, LEVEL;
	
	public static int getPitHeight(int y) {
		if (y == 4) // has duplicate in generateWithSize
			y = 10;
		else if (y == 2)
			y = 5;
		return y * LevelData.TILE_SIZE_Y;
	}
	
	public GridGenerator() {
		String prefix = "de/acagamics/roteschlupfmuetze/level/";
		fill = getImage(prefix + "stairs_face_1WU_1.png");
		edgeToLeft = new BufferedImage[0]; // TODO: add small edges
		edgeToRight = new BufferedImage[0];
		longEdgeToLeft = new BufferedImage[]{
				getImage(prefix + "stairs_left_cliff_2HU_1.png", LONG_EDGE_HEIGHT),
				getImage(prefix + "stairs_left_cliff_2HU_2.png", LONG_EDGE_HEIGHT),
				getImage(prefix + "stairs_left_cliff_2HU_3.png", LONG_EDGE_HEIGHT)};
		longEdgeToRight = new BufferedImage[]{
				getImage(prefix + "stairs_right_cliff_2HU_1.png", LONG_EDGE_HEIGHT),
				getImage(prefix + "stairs_right_cliff_2HU_2.png", LONG_EDGE_HEIGHT),
				getImage(prefix + "stairs_right_cliff_2HU_3.png", LONG_EDGE_HEIGHT)};
		cornerToLeft = new BufferedImage[]{getImage(prefix + "stairs_left_surface_grass_1WU_1.png")};
		cornerToRight = new BufferedImage[]{
				getImage(prefix + "stairs_right_surface_1WU_2.png"),
				getImage(prefix + "stairs_right_surface_grass_1WU_1.png")};
		surface = new BufferedImage[]{
				getImage(prefix + "stairs_surface_grass_1WU_1.png"),
				getImage(prefix + "stairs_surface_grass_1WU_2.png"),
				getImage(prefix + "stairs_surface_grass_1WU_3.png"),
				getImage(prefix + "stairs_surface_grass_1WU_4.png")};
		pitSurface = new BufferedImage[]{getImage(prefix + "stairs_surface_plain_1WU_1.png")};
	}
	
	public void generateWithSize(int x, int y, LevelData levelData,
			SpriteGroup STATIC, SpriteGroup MOVABLE, SpriteGroup COLLISION, SpriteGroup LEVEL) {
		if(y == 4) y = 10;
		else if(y==2) y = 5;
		this.STATIC = STATIC;
		this.MOVABLE = MOVABLE;
		this.COLLISION = COLLISION;
		this.LEVEL = LEVEL;
		
		int startX = levelData.getPitOffsetX();
		int startY = levelData.getPitOffsetY();
		int upperY = startY - (1 + y) * LevelData.TILE_SIZE_Y;
		int lowerYrepeats = 1 + startY / LevelData.TILE_SIZE_Y;
		int leftXrepeats = startX / LevelData.TILE_SIZE_X;
		int rightStartX = startX + x * LevelData.TILE_SIZE_X;
		int rightXrepeats = (RoteSchlupfmuetze.WIDTH - rightStartX) / LevelData.TILE_SIZE_X;
		
		createEdge(startX - LevelData.TILE_SIZE_X, upperY, y, lowerYrepeats, true);
		fillSide(startX - (1 + leftXrepeats)*LevelData.TILE_SIZE_X, upperY,
				leftXrepeats, lowerYrepeats + y + 1, false);
		createInterior(startX, startY - LevelData.TILE_SIZE_Y, x, lowerYrepeats);
		fillSide(startX-LevelData.TILE_SIZE_X, upperY, x+2, lowerYrepeats + y + 1, true);
		createEdge(rightStartX, upperY, y, lowerYrepeats, false);
		fillSide(rightStartX + LevelData.TILE_SIZE_X, upperY,
				rightXrepeats, lowerYrepeats + y + 1, false);
	}
	
	private void createEdge(int startX, int startY, int yHeight, int repeatY, boolean left) {
		BufferedImage image;
		BufferedImage[] edges;
		if(left) {
			image = randomFromArray(cornerToRight);
			if(yHeight == LONG_EDGE_HEIGHT)
				edges = longEdgeToRight;
			else if(yHeight == SHORT_EDGE_HEIGHT)
				edges = edgeToRight;
			else throw new java.lang.RuntimeException("unknown height "+yHeight);
		} else {
			image = randomFromArray(cornerToLeft);
			if(yHeight == LONG_EDGE_HEIGHT)
				edges = longEdgeToLeft;
			else if(yHeight == LONG_EDGE_HEIGHT)
				edges = edgeToLeft;
			else throw new java.lang.RuntimeException("unknown height "+yHeight);
		}
		Sprite cover = new Sprite(image, startX, startY);
		addSprite(cover, false, false);
		Sprite edge = new Sprite(randomFromArray(edges), startX, startY + LevelData.TILE_SIZE_Y);
		addSprite(edge, false, true);
		startY += (yHeight + 1) * LevelData.TILE_SIZE_Y;
		for(int y = 0; y < repeatY; y++) {
			fill(startX, startY + y * LevelData.TILE_SIZE_Y, false);
		}
	}
	
	private void fillSide(int startX, int startY, int repeatX, int repeatY, boolean movable) {
		for(int x = 0; x < repeatX; x++) {
			Sprite cover = new Sprite(randomFromArray(surface),
					startX + x * LevelData.TILE_SIZE_X, startY);
			addSprite(cover, movable, false);
			for(int y = 1; y < repeatY; y++) {
				fill(startX + x * LevelData.TILE_SIZE_X,
					startY + y * LevelData.TILE_SIZE_Y,
					movable);
			}
		}
	}
	
	private void createInterior(int startX, int startY, int repeatX, int repeatY) {
		for(int x = 0; x < repeatX; x++) {
			Sprite cover = new Sprite(randomFromArray(pitSurface),
					startX + x * LevelData.TILE_SIZE_X, startY);
			addSprite(cover, false, false);
			for(int y = 1; y < repeatY; y++) {
				fill(startX + x * LevelData.TILE_SIZE_X,
					startY + y * LevelData.TILE_SIZE_Y,
					false);
			}
		}
	}
	
	private void fill(int x, int y, boolean movable) {
		Sprite sprite = new Sprite(fill, x, y);
		addSprite(sprite, movable, true);
	}
	
	private void addSprite(Sprite sprite, boolean movable, boolean collision) {
		if (movable)
			MOVABLE.add(sprite);
		else
			STATIC.add(sprite);
		if (collision)
			COLLISION.add(sprite);
		LEVEL.add(sprite);
	}
	
	private BufferedImage randomFromArray(BufferedImage[] ary) {
		return ary[random.nextInt(ary.length)];
	}
	
	private BufferedImage getImage(String path) {
		return getImage(path, 1);
	}
	private BufferedImage getImage(String path, int yScale) {
		BufferedImage image = RoteSchlupfmuetze.loadImage(path);
		return ImageHelper.scaleImage(image, LevelData.TILE_SIZE_X, yScale*LevelData.TILE_SIZE_Y);
	}
}
